import {inject, reactive, App} from "vue";

interface Option {
  state: () => {[k in string]: any};
  mutations?: {[k in string]: (state: any) => void};
  actions?: {[k in string]: (...args: any[]) => void};
}

const STOREKEY = "__STORE__";
class Store {
  public state: any;
  private mutations?: {[k in string]: (...args: any[]) => void};
  private actions?: {[k in string]: (...args: any[]) => void};
  constructor(option: Option) {
    this.state = reactive(option.state());
    this.mutations = option.mutations;
    this.actions = option.actions;
  }

  install(app: App) {
    app.provide(STOREKEY, this);
  }
  commit(k: string, ...args: any[]) {
    const {mutations, state} = this;
    mutations?.[k](state, ...args);
  }
  dispatch(k: string, ...args: any[]) {
    this.actions?.[k](this,...args);
  }
}

export function createStore(option: Option) {
  return new Store(option);
}

export function useStore() {
  return inject(STOREKEY) as Store;
}
